
package com.vanda.db.util;


import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.hibernate.Hibernate;
import net.sf.hibernate.type.Type;

import com.vanda.db.exception.DbException;

/**
 * 数据库工具类<br>
 * 
 * @author 王瑛<br>
 * @version Version 1.00<br>
 */
public class DBUtils {
	/** 保存java类型与sql类型对应关系 */
	private static HashMap hmType = null;
	/** Hibernate类型 */
	public static int HIBERNATE_TYPE = 0;
	/** SQL 类型 */
	public static int SQL_TYPE = 1;
	
	static {
		hmType = new HashMap();
		hmType.put(
			"java.lang.String",
			new Object[] { Hibernate.STRING, new Integer(Types.VARCHAR)});
		hmType.put(
			"java.lang.Integer",
			new Object[] { Hibernate.INTEGER, new Integer(Types.INTEGER)});
		hmType.put(
			"java.lang.Long",
			new Object[] { Hibernate.LONG, new Integer(Types.BIGINT)});
		hmType.put(
			"java.lang.Float",
			new Object[] { Hibernate.FLOAT, new Integer(Types.FLOAT)});
		hmType.put(
			"java.lang.Double",
			new Object[] { Hibernate.DOUBLE, new Integer(Types.DOUBLE)});
		hmType.put(
			"java.sql.Date",
			new Object[] { Hibernate.DATE, new Integer(Types.DATE)});
		hmType.put(
			"java.sql.Time",
			new Object[] { Hibernate.TIME, new Integer(Types.TIME)});
		hmType.put(
			"java.sql.Timestamp",
			new Object[] { Hibernate.TIMESTAMP, new Integer(Types.TIMESTAMP)});
		hmType.put(
			"java.lang.Boolean",
			new Object[] { Hibernate.BOOLEAN, new Integer(Types.BIT)});
		hmType.put(
			"java.math.BigDecimal",
			new Object[] { Hibernate.BIG_DECIMAL, new Integer(Types.DOUBLE)});
	}
	
	/**
	 * 返回Java类型对应的sql或hql类型
	 * @param objs java类型数组
	 * @param index xql类型，0-hql类型，1-sql类型
	 * @return
	 * @throws DbException
	 */
	public static Object[] convert(Object[] objs, int index) throws DbException {
		List types = new ArrayList();
		for (int i = 0; i < objs.length; i++) {
			String clsName = objs[i].getClass().getName();
			Object[] objTypes = (Object[]) hmType.get(clsName);
			if (objTypes == null) {
				throw new DbException(
					"没有为[" + clsName + "]类型找到对应的Hibernate或SQL类型!");
			}
			types.add(objTypes[index]);
		}
		Object[] objTypes = null;
		if (index == HIBERNATE_TYPE) {
			objTypes = types.toArray(new Type[0]);
		} else {
			objTypes = types.toArray(new Integer[0]);
		}
		return objTypes;
	}
	
	final static String NOTEMPTYSTRING = "`~!@#$%^&*-=_+|;',.:<>?";
	/**
	 * 校验字符是否为空
	 * @param ch
	 * @return
	 */
	public static boolean isEmptyChar(char ch){
		if(ch == ' '){
			return true;
		}
		if(ch >= 'A' && ch <= 'Z'){
			return false;
		}
		if(ch >= 'a' && ch <= 'z'){
			return false;
		}
		if(ch >= '0' && ch <= '9'){
			return false;
		}
		
		int pos = NOTEMPTYSTRING.indexOf(ch+"");
		if(pos >= 0){
			return false;
		}

		return true;
	}
	
	
	public static String[] getQueryField(ResultSet rs) throws SQLException {
		java.sql.ResultSetMetaData dma = rs.getMetaData();
		String[] sFields = new String[dma.getColumnCount()];
		for (int i = 0; i < dma.getColumnCount(); i++) {
			sFields[i] = dma.getColumnName(i + 1).toLowerCase().trim();
		}
		return sFields;
	}
	
	public static Object getRowObject(
		Class cRecord,
		ResultSet rs,
		String[] sFields,
		HashMap hmTable)
		throws DbException {
		try {
			Object dataBean = (Object) cRecord.newInstance();
			//是否是Map类型，如果是，则不用反射
			boolean bMap = dataBean instanceof Map;
			ResultSetMetaData rsMetaData = null;
			if(bMap == true){
				rsMetaData = rs.getMetaData();
			}
			
			for (int i = 0; i < sFields.length; i++) {
				if(bMap){
					Object result = getValue(rsMetaData,rs,i+1);
					((Map)dataBean).put(sFields[i].toLowerCase(),result);
				}else{
					Object[] param = new Object[1];
					Method setMethod = (Method) hmTable.get(sFields[i]);
					if (setMethod == null) {
						//throw new Exception("字段["+sFields[i]+"]在AbstractData类没有定义,请检查AbstractData类!");
						continue;
					}
					param[0] = getValue(setMethod, rs, sFields[i]);
					if (param[0] != null) {
						setMethod.invoke(dataBean, param);
					}
				}

			}
			
			return dataBean;
		} catch (Exception e) {
			e.printStackTrace();
			throw new DbException(e);
		} 
	}
	
	private static Object getValue(ResultSetMetaData rsMetaData,ResultSet rs,int index) throws SQLException{
		int columnType = rsMetaData.getColumnType(index);
		switch (columnType) {
			case Types.CHAR :
			case Types.VARCHAR :
			case Types.LONGVARCHAR :
				return rs.getString(index);
			case Types.BIT :
				boolean bTmp = rs.getBoolean(index);
				if (rs.wasNull())
					return null;
				else
					return new Boolean(bTmp);
			case Types.TINYINT :
			case Types.SMALLINT :
			case Types.INTEGER :
				int iTmp = rs.getInt(index);
				if (rs.wasNull())
					return null;
				else
					return new Integer(iTmp);
			case Types.BIGINT :
				long lTmp = rs.getLong(index);
				if (rs.wasNull())
					return null;
				else
					return new Long(lTmp);
				
			case Types.FLOAT :
			case Types.DOUBLE :
				double dTmp = rs.getDouble(index);
				if (rs.wasNull())
					return null;
				else
					return new Double(dTmp);
				

			case Types.TIME :
				return rs.getTime(index);
				
			case Types.DATE :
			case Types.TIMESTAMP :
				return rs.getTimestamp(index);
				
			case Types.NULL :
				return null;
			default :
				return rs.getObject(index);
				
		}

	}
	private static Object getValue(Method setMethod, ResultSet rs, String sField) {
		Class ctype = setMethod.getParameterTypes()[0];
		String stype = ctype.getName();
		Object obj = null;
		try {
			obj = rs.getObject(sField);
			if (obj == null) {
				return null;
			}
			if (stype.equals("java.lang.String")) {
				String svalue = rs.getString(sField);
				obj = svalue;
			} else if (
				stype.equals("float") || stype.equals("java.lang.Float")) {
				float fvalue = rs.getFloat(sField);
				obj = new Float(fvalue);
			} else if (
				stype.equals("int") || stype.equals("java.lang.Integer")) {
				int ivalue = rs.getInt(sField);
				obj = new Integer(ivalue);
			} else if (
				stype.equals("double") || stype.equals("java.lang.Double")) {
				double dvalue = rs.getDouble(sField);
				obj = new Double(dvalue);
			} else if (
				stype.equals("long") || stype.equals("java.lang.Long")) {
				long lvalue = rs.getLong(sField);
				obj = new Long(lvalue);
			} else if (stype.equals("java.sql.Timestamp")) {
				obj = rs.getTimestamp(sField);
			} else if (stype.equals("boolean")) {
				boolean bvalue = rs.getBoolean(sField);
				obj = new Boolean(bvalue);
			} else if (stype.equals("byte")) {
				byte bt = rs.getByte(sField);
				obj = new Byte(bt);
			} else if (stype.equals("short")) {
				short svalue = rs.getShort(sField);
				obj = new Short(svalue);
			} else if (stype.equals("java.sql.Date")) {
				obj = rs.getDate(sField);
			} else if (stype.equals("java.sql.Time")) {
				obj = rs.getTime(sField);
			} else if (stype.equals("java.sql.Blob")) {
				obj = rs.getBlob(sField);
			} else if (stype.equals("java.sql.Clob")) {
				obj = rs.getClob(sField);
			}
		} catch (Exception e) {
			obj = null;
		}
		return obj;
	}
	

}
